package io.gitee.horizon007.webspider.transformer;

import io.gitee.horizon007.webspider.WebSpider;
import io.gitee.horizon007.webspider.annotation.Context;
import io.gitee.horizon007.webspider.metadata.PropertyMetadata;
import org.apache.commons.collections4.CollectionUtils;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Attributes;
import org.jsoup.select.Elements;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AttributeTransformer implements ValueTransformer {

    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AttributeName {
        String value();
    }

    @Override
    public Object transform(WebSpider webSpider, Elements elements, Object instance, PropertyMetadata propertyMetadata, Context annotation) throws Exception {

        if (propertyMetadata.isMap()) {
            if (CollectionUtils.isEmpty(elements)) {
                return Collections.emptyMap();
            }


            List<? extends Class<?>> genericParameterList = propertyMetadata.getGenericParameterList();
            if (CollectionUtils.isNotEmpty(genericParameterList)
                    && genericParameterList.get(0) == String.class
                    && genericParameterList.get(0) == genericParameterList.get(1)
            ) {
                Attributes attributes = elements.get(0).attributes();
                Map<String, String> map = new HashMap<>(attributes.size());
                for (Attribute attribute : attributes) {
                    map.put(attribute.getKey(), attribute.getValue());
                }
                return Collections.unmodifiableMap(map);
            }
        } else if (propertyMetadata.getClassType() == String.class) {

            if (CollectionUtils.isEmpty(elements)) {
                return null;
            }

            AttributeName attributeNameAnnotation = propertyMetadata.getAnnotation(AttributeName.class);
            String attr = attributeNameAnnotation == null ?
                    propertyMetadata.getName() :
                    attributeNameAnnotation.value();

            Attributes attributes = elements.get(0).attributes();
            if (!attributes.hasKeyIgnoreCase(attr)) {
                return null;
            }
            return attributes.getIgnoreCase(attr);

        }


        throw new Exception(String.format(
                "When using %s, only data type Map<String, String>/String is supported, and the error is: '%s#%s'",
                getClass().getSimpleName(),
                propertyMetadata.getOwner().getType().getName(),
                propertyMetadata.getName()
        ));
    }
}
